#include "router.h"

#include "serialization/asn1.h"
#include "node_ble.h"
#include "node_coreio.h"
#include "node_extapp.h"
#include "node_i2c.h"
#include "node_sidecar.h"
#include "node_sam.h"
#include "t1.h"

#include "Debug.h"
//	#include "nrf_log.h"
#include <stddef.h>
#include <stdint.h>


typedef int (*node_handler)(t1_inf_t *inf, /*t1_len_t*/ uint16_t len);
typedef uint8_t *message_t;

typedef struct {
    ASN1_Node_id nodeid;
    node_handler handler;
} router_node_t;

enum {
    ROUTE_NULL,
    ROUTE_CORE,
    ROUTE_SAM,
    ROUTE_HF,
    ROUTE_BLE,
    ROUTE_COREIO,
    ROUTE_SIDECAR,
    ROUTE_EXT_APP,
    ROUTE_I2C,
    TOTAL_ROUTES
};

static router_node_t const routes[TOTAL_ROUTES] = {
    // clang-format off
    /* NAME             NODEID          HANDLER                     */
    [ROUTE_NULL]    = { NODE_NULL,      NULL                        },
    [ROUTE_CORE]    = { NODE_CORE,      NULL                        },
    [ROUTE_SAM]     = { NODE_SAM,       node_sam_handler            },
    [ROUTE_HF]      = { NODE_HF,        NULL                        },
    [ROUTE_BLE]     = { NODE_BLE,       node_ble_handler            },
    [ROUTE_COREIO]  = { NODE_COREIO,    node_coreio_handler         },
    [ROUTE_SIDECAR] = { NODE_SIDECAR,   node_sidecar_handler        },
    [ROUTE_EXT_APP] = { NODE_EXT_APP,   NULL         				},    
    [ROUTE_I2C]     = { NODE_I2C,       node_i2c_handler            }
}; // clang-format on

int router_route(t1_inf_t *inf, /*t1_len_t*/ uint16_t len) {
    //[FROM, TO, REPLY TO]
    payload_header_t *header = &(inf->header);

    /* Try to find node */
    for (int i = 0; i < TOTAL_ROUTES; i++) {
        if (routes[i].nodeid == header->destination) {
            if (routes[i].handler == NULL) {
                LOG_W("CANNOT ROUTE: No handler for node 0x%02X", header->destination);
                break;
            }
            
            return routes[i].handler(inf, len);
        }
    }
    LOG_W("CANNOT ROUTE: NODEID 0x%02X not found", header->destination);
    return 1;
}


